package org.mathcloud.math.core.generic.factory;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

import org.mathcloud.math.core.common.factory.QuantityObjectFactory;
import org.mathcloud.math.core.common.quantity.QuantityObject;
import org.mathcloud.math.core.common.signature.QuantityObjectSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webequa.core.generic.factory.GenericQuantityObjectFactory;


public class GenericQuantityObjectFactory implements QuantityObjectFactory
{
	/*	method to get new instance of QuantityObject for given class
	 * 	class should implement RealNumber, ComplexNumber or MatrixObject interface
	 * 	otherwise method will return null
	 * */
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public QuantityObject newInstance(QuantityObjectSignature arg0)
	{
		String impClassName = getImplementationClassName(arg0);
		Class implementationClass;
		try
		{
			implementationClass = Class.forName(impClassName);
			if (arg0.isRealNumberSignature()||arg0.isComplexNumberSignature())
			{
				try
				{
					return (QuantityObject)implementationClass.newInstance();
				} catch (InstantiationException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				} catch (IllegalAccessException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				}				
			}
			else if (arg0.isMatrix())
			{
				Constructor constructor;
				try
				{
					constructor = implementationClass.getConstructor(Integer.class,Integer.class);
					return (QuantityObject) constructor.newInstance(arg0.getDimensions()[0],arg0.getDimensions()[1]);
				} catch (SecurityException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				} catch (NoSuchMethodException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				}
				catch (IllegalArgumentException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				} catch (InstantiationException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				} catch (IllegalAccessException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				} catch (InvocationTargetException e)
				{
					log.error("Cannot create instance - ",e);
					return null;
				}
			}
			else return null;
		} catch (ClassNotFoundException e1)
		{
			log.error("Cannot create instance - ",e1);
			return null;
		}
	}	
	
	
	public void setProperties(String fileName)
	{
		try
		{
			properties = new Properties();
			properties.load(new FileInputStream(fileName));						
		} catch (FileNotFoundException e)
		{
			log.error("Cannot set properties for factory - ",e);
		} catch (IOException e)
		{
			log.error("Cannot set properties for factory - ",e);
		}
	}
	public Properties getProperties()
	{
		return properties;
	}

	public String getImplementationClassName(QuantityObjectSignature arg0)
	{
		if (properties!=null)
		{
			String key = arg0.getRealizationName()+".";
			if (arg0.isRealNumberSignature())
				key +="real.number"; 
			else if (arg0.isComplexNumberSignature())
				key+="complex.number";
			else if (arg0.isRealMatrixSignature())
				key+="real.matrix";
			else if (arg0.isComplexMatrixSignature())
				key+="complex.matrix";
			return properties.getProperty(key); 
		}
		else return null;
	}

	private Properties properties;
	private static final Logger log = LoggerFactory.getLogger(GenericQuantityObjectFactory.class);
}
